package com.saicent.note.core.impl;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.saicent.note.core.Article;
import com.saicent.note.core.ArticleLoader;
import com.saicent.note.core.ArticleManager;
import com.saicent.note.core.Category;
import com.saicent.note.core.Configuration;
import com.saicent.support.utils.StringUtils;

public class ArticleManagerImpl implements ArticleManager {

	private Map<String, Article> articlesMappedById = new HashMap<>();
	private Map<String, List<Article>> articlesMappedByCategory = new HashMap<>();
	private Map<String, Category> categoriesMappedById;
	
	private Configuration configuration = null;
	
	private List<Category> allCategories = new ArrayList<>();
	private List<Article> allArticles = new ArrayList<>();
	
	public ArticleManagerImpl(Configuration configuration) {
		this.configuration = configuration;
		init();
	}
	
	public void init () {
		String configLocation = configuration.getScanningLocation();
		
		// Load All Articles.
		if (configLocation != null) {
			ArticleLoader articleLoader = new AutoArticleLoader(configLocation);
			articleLoader.setWorkDirectory(configuration.getWorkDirectory());
			Collection<Article> temp = articleLoader.loadArticles();
			if (temp != null) {
				allArticles.addAll(temp);
			}
		}
		
		// Filter Repeated Articles.
		organizeArticles();
		organizeCategories(allArticles);
	}
	
	private void organizeArticles() {
		allArticles = filterRepeatedArticles(allArticles);
		articlesMappedById = doOrganizeArticles(allArticles);
	}
	
	private List<Article> filterRepeatedArticles(Collection<Article> articles) {
		HashSet<Article> hashSet = new HashSet<>();
		for (Article article : articles) {
			hashSet.add(article);
		}
		List<Article> result = new ArrayList<>();
		result.addAll(hashSet);
		return result;
	}
	
	private void organizeCategories(Collection<Article> articles) {
		Set<String> categoryNames = new HashSet<>();
		for (Article article : articles) {
			for (String aeticleCagegory : article.getCategories()) {
				List<Article> mappedArticles = articlesMappedByCategory.get(aeticleCagegory);
				if (mappedArticles == null) {
					mappedArticles = new ArrayList<>();
					articlesMappedByCategory.put(aeticleCagegory, mappedArticles);
				}
				mappedArticles.add(article);
			}
			categoryNames.addAll(article.getCategories());
		}
		for (String categoryName : categoryNames) {
			allCategories.add(new Category(null, categoryName));
		}
		categoriesMappedById = doOrganizeCategories(allCategories);
	}
	
	protected Map<String, Article> doOrganizeArticles(List<Article> articles) {
		Map<String, Article> map = new HashMap<>();
		int index = 1;
		for (Article article : allArticles) {
			String articleId = "thread-" + StringUtils.leftPad(String.valueOf(index++), 4, "0");
			article.setId(articleId);
			map.put(articleId, article);
		}
		return map;
	}
	
	protected Map<String, Category> doOrganizeCategories(List<Category> categories) {
		Map<String, Category> map = new HashMap<>();
		int index = 1;
		for (Category category : categories) {
			String categoryId = StringUtils.leftPad(String.valueOf(index++), 2, "0");
			category.setId(categoryId);
			map.put(categoryId, category);
		}
		return map;
	}
	
	@Override
	public List<Article> allArticles() {
		return allArticles;
	}

	@Override
	public List<Category> allCategories() {
		return allCategories;
	}

	@Override
	public Category getCategory(String categoryId) {
		return categoriesMappedById.get(categoryId);
	}

	@Override
	public List<Article> getArticlesByCategory(String categoryId) {
		return articlesMappedByCategory.get(categoriesMappedById.get(categoryId).getName());
	}

	@Override
	public Article getArticle(String articleId) {
		return articlesMappedById.get(articleId);
	}

	@Override
	public void reload() {
		articlesMappedById.clear();
		articlesMappedByCategory.clear();
		categoriesMappedById.clear();
		allCategories.clear();
		allArticles.clear();
		init();
	}

	@Override
	public void deleteArticle(String articleId) {
		Article article = getArticle(articleId);
		Path articleFilepath = Paths.get(configuration.getWorkDirectory(), article.getLocation());
		File articleFile = articleFilepath.toFile();
		articleFile.delete();
	}

}
